package com.vagavaga.tx;

import java.lang.reflect.Proxy;
import java.sql.Connection;
import java.sql.SQLException;

public enum TransactionAttribute {
    // /**
    // * If the client is running within a transaction and invokes the
    // enterprise
    // * bean's method, the method executes within the client's transaction. If
    // * the client is not associated with a transaction, the container starts a
    // * new transaction before running the method.
    // *
    // * The Required attribute will work for most transactions. Therefore, you
    // * may want to use it as a default, at least in the early phases of
    // * development. Because transaction attributes are declarative, you can
    // * easily change them at a later time.
    // */
    // Required {
    // @Override
    // Connection connection(String n) throws SQLException {
    // if (TransactionManager.isInTransaction(n)) {
    // Connection conn =
    // TransactionManager.getCurrentTransaction(n).getConnection();
    // return (Connection) Proxy.newProxyInstance(
    // conn.getClass().getClassLoader(),
    // new Class[] { Connection.class },
    // new ChildTransactionInterceptor(n));
    // }
    //
    // Connection conn = DataSourceRegistry.instance().get(n).getConnection();
    // Connection wrapped = (Connection) Proxy.newProxyInstance(
    // conn.getClass().getClassLoader(),
    // new Class[] { Connection.class },
    // new TransactionInterceptor(n, conn));
    // wrapped.setAutoCommit(false);
    // return wrapped;
    //
    // }
    // },
    // /**
    // * If the client is running within a transaction and invokes the
    // enterprise
    // * bean's method, the container takes the following steps:
    // *
    // * 1. Suspends the client's transaction 2. Starts a new transaction 3.
    // * Delegates the call to the method 4. Resumes the client's transaction
    // * after the method completes
    // *
    // * If the client is not associated with a transaction, the container
    // starts
    // * a new transaction before running the method.
    // *
    // * You should use the RequiresNew attribute when you want to ensure that
    // the
    // * method always runs within a new transaction.
    // */
    // RequiresNew {
    // @Override
    // Connection connection(String n) throws SQLException {
    // Connection conn = DataSourceRegistry.instance().get(n).getConnection();
    // Connection wrapped = (Connection) Proxy.newProxyInstance(
    // conn.getClass().getClassLoader(),
    // new Class[] { Connection.class },
    // new TransactionInterceptor(n, conn));
    // wrapped.setAutoCommit(false);
    // return wrapped;
    // }
    // },
    //
    // /**
    // * If the client is running within a transaction and invokes the
    // enterprise
    // * bean's method, the method executes within the client's transaction. If
    // * the client is not associated with a transaction, the container throws
    // the
    // * TransactionRequiredException.
    // *
    // * Use the Mandatory attribute if the enterprise bean's method must use
    // the
    // * transaction of the client.
    // */
    // Mandatory {
    // @Override
    // Connection connection(String n) throws SQLException {
    // if (!TransactionManager.isInTransaction(n)) throw new
    // SQLException("Transaction required");
    //
    // Connection conn =
    // TransactionManager.getCurrentTransaction(n).getConnection();
    // return (Connection) Proxy.newProxyInstance(
    // conn.getClass().getClassLoader(),
    // new Class[] { Connection.class },
    // new ChildTransactionInterceptor(n));
    // }
    // },
    //
    // /**
    // * If the client is running within a transaction and invokes the
    // enterprise
    // * bean's method, the container suspends the client's transaction before
    // * invoking the method. After the method has completed, the container
    // * resumes the client's transaction.
    // *
    // * If the client is not associated with a transaction, the container does
    // * not start a new transaction before running the method.
    // *
    // * Use the NotSupported attribute for methods that don't need
    // transactions.
    // * Because transactions involve overhead, this attribute may improve
    // * performance.
    // */
    // NotSupported {
    // @Override
    // Connection connection(String n) throws SQLException {
    // return DataSourceRegistry.instance().get(n).getConnection();
    // }
    // },
    //
    // /**
    // * If the client is running within a transaction and invokes the
    // enterprise
    // * bean's method, the method executes within the client's transaction. If
    // * the client is not associated with a transaction, the container does not
    // * start a new transaction before running the method.
    // *
    // * Because the transactional behavior of the method may vary, you should
    // use
    // * the Supports attribute with caution.
    // */
    // Supports {
    // @Override
    // Connection connection(String n) throws SQLException {
    // if (TransactionManager.isInTransaction(n)) {
    // if (TransactionManager.isInTransaction(n)) {
    // Connection conn =
    // TransactionManager.getCurrentTransaction(n).getConnection();
    // return (Connection) Proxy.newProxyInstance(
    // conn.getClass().getClassLoader(),
    // new Class[] { Connection.class },
    // new ChildTransactionInterceptor(n));
    // }
    // }
    // return DataSourceRegistry.instance().get(n).getConnection();
    // }
    // },
    //
    // /**
    // * If the client is running within a transaction and invokes the
    // enterprise
    // * bean's method, the container throws a RemoteException. If the client is
    // * not associated with a transaction, the container does not start a new
    // * transaction before running the method.
    // */
    // Never {
    // @Override
    // Connection connection(String n) throws SQLException {
    // if (TransactionManager.isInTransaction(n)) throw new
    // SQLException("Transaction not supported");
    //
    // return DataSourceRegistry.instance().get(n).getConnection();
    // }
    // };

    Tx {
        @Override
        Connection connection(String n) throws SQLException {
            if (TransactionManager.isInTransaction(n)) {
                Connection conn = TransactionManager.getCurrentTransaction(n).getConnection();
                return (Connection) Proxy.newProxyInstance(
                        conn.getClass().getClassLoader(),
                        new Class[] { Connection.class },
                        new ChildTransactionInterceptor(n));
            }

            Connection conn = DataSourceRegistry.instance().get(n).getConnection();
            Connection wrapped = (Connection) Proxy.newProxyInstance(
                    conn.getClass().getClassLoader(),
                    new Class[] { Connection.class },
                    new TransactionInterceptor(n, conn));
            return wrapped;
        }
    },
    Plain {
        @Override
        Connection connection(String name) throws SQLException {
            return DataSourceRegistry.instance().get(name).getConnection();
        }
    };
    abstract Connection connection(String name) throws SQLException;
}
